/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-05-13     Administrator       the first version
 */
#include "data.h"

rt_device_t k230_serial;
char k230_rx_buf[RX_BUFFER_K230_SIZE];

rt_device_t JXB_serial;//机械臂串口
rt_device_t Song_serial;//语音模块串口
rt_device_t LCD_serial;//LCD模块串口


//环形缓冲区
struct rt_ringbuffer k230_rx_rb;
uint8_t k230_raw_buf[RX_RINGBUF_K230_SIZE];

//物体的标签，x坐标，距离
char toy_label[20] = {0};  // 保存标签
int toy_x;
int toy_y;
float toy_distance;


//k230串口初始化
int k230_uart_init(void)
{
    k230_serial = rt_device_find(K230_UART_NAME);
    if (!k230_serial)
    {
        rt_kprintf("K230 UART not found!\n");
        return RT_ERROR;
    }

    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
    config.baud_rate = BAUD_RATE_115200;  // 根据实际配置
    config.bufsz     = 256;
    rt_device_control(k230_serial, RT_DEVICE_CTRL_CONFIG, &config);

    if (rt_device_open(k230_serial, RT_DEVICE_FLAG_DMA_RX) != RT_EOK)
    {
        rt_kprintf("Open K230 UART failed!\n");
        return RT_ERROR;
    }

    rt_ringbuffer_init(&k230_rx_rb, k230_raw_buf, RX_RINGBUF_SIZE);

    rt_device_set_rx_indicate(k230_serial, k230_uart_rx_callback);

    rt_kprintf("K230 UART init OK.\n");
    return RT_EOK;
}

/*机械臂串口接口初始化*/
int JXB_init(void)
{
    /* 查找串口设备 */
    JXB_serial = rt_device_find(JXB_UART_NAME);
    if (!JXB_serial) {
        rt_kprintf("UART device %s not found!\n", JXB_UART_NAME);
        return RT_ERROR;
    }

    /* 配置串口参数 */
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
    config.baud_rate = BAUD_RATE_9600;
    config.bufsz = 256;
    rt_device_control(JXB_serial, RT_DEVICE_CTRL_CONFIG, &config);

    /* 以DMA接收+轮询发送模式打开设备 */
    if (rt_device_open(JXB_serial, RT_DEVICE_FLAG_DMA_RX) != RT_EOK) {
        rt_kprintf("Failed to open UART!\n");
        return RT_ERROR;
    }

    rt_kprintf("JXB enable succeed\r\n");

    return RT_EOK;
}

//语音串口初始化
int Song_uart_init(void)
{
    Song_serial = rt_device_find(Song_UART_NAME);
    if (!Song_serial)
    {
        rt_kprintf("Song_serial UART not found!\n");
        return RT_ERROR;
    }

    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
    config.baud_rate = BAUD_RATE_9600;  // 根据实际配置
    config.bufsz     = 256;
    rt_device_control(Song_serial, RT_DEVICE_CTRL_CONFIG, &config);

    if (rt_device_open(Song_serial, RT_DEVICE_FLAG_DMA_RX) != RT_EOK)
    {
        rt_kprintf("Open Song_serial UART failed!\n");
        return RT_ERROR;
    }

    rt_kprintf("Song_serial UART init OK.\n");
    return RT_EOK;
}

//屏幕串口初始化
int LCD_uart_init(void)
{
    LCD_serial = rt_device_find(LCD_UART_NAME);
    if (!LCD_serial)
    {
        rt_kprintf("LCD_serial UART not found!\n");
        return RT_ERROR;
    }

    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
    config.baud_rate = BAUD_RATE_9600;  // 根据实际配置
    config.bufsz     = 256;
    rt_device_control(LCD_serial, RT_DEVICE_CTRL_CONFIG, &config);

    if (rt_device_open(LCD_serial, RT_DEVICE_FLAG_DMA_RX) != RT_EOK)
    {
        rt_kprintf("Open LCD_serial UART failed!\n");
        return RT_ERROR;
    }

    rt_kprintf("LCD_serial UART init OK.\n");
    return RT_EOK;
}

rt_err_t k230_uart_rx_callback(rt_device_t dev, rt_size_t size)
{
    rt_size_t len = rt_device_read(dev, 0, k230_rx_buf, RX_BUFFER_SIZE);
    if (len > 0)
    {
        rt_ringbuffer_put(&k230_rx_rb, (uint8_t *)k230_rx_buf, len);
    }
    return RT_EOK;
}


void k230_data_task(void *parameter)
{
    rt_tick_t last_time = rt_tick_get();
    char ch = 0;

    // 接收字段缓冲
    char label_buf[20] = {0};
    char x_buf[10] = {0};
    char y_buf[10] = {0};
    char dist_buf[10] = {0};

    int label_idx = 0, x_idx = 0,  y_idx = 0, d_idx = 0;

    static uint8_t k_state = WAIT_LABEL;

    while (1)
    {

        while (rt_ringbuffer_getchar(&k230_rx_rb, (rt_uint8_t *)&ch) == 1)
        {
            if (ch == '\n')  // 一条数据结束
            {
                // 终结符处理
                label_buf[label_idx] = '\0';
                x_buf[x_idx] = '\0';
                y_buf[y_idx] = '\0';
                dist_buf[d_idx] = '\0';

                toy_x = atoi(x_buf);// 字符串转换为 int 类型（整数)
                toy_y = atoi(y_buf);
                toy_distance = atof(dist_buf);// 把一个字符串转换为 float 类型（浮点数）
                strncpy(toy_label, label_buf, sizeof(toy_label) - 1);  // 拷贝label，防止越界

                toy_label[sizeof(toy_label) - 1] = '\0'; // 确保字符串结束

//                rt_kprintf("[K230 FSM] label=%s, x=%d, dist=%d\n", toy_label, toy_x, (rt_uint16_t)toy_distance);
//                 rt_kprintf("[K230 FSM] label=%s, x=%d, y=%d, dist=%d\n", toy_label, toy_x, toy_y, (rt_uint16_t)toy_distance);

                // 重置状态机
                k_state = WAIT_LABEL;
                label_idx = x_idx = y_idx = d_idx = 0;
                continue;
            }

            switch (k_state)
            {
                case WAIT_LABEL:
                    // 第一个字段，进入读取 label 状态
                    label_idx = 0;
                    k_state = READ_LABEL;
                    // 继续处理当前字符
                    /* fallthrough */

                case READ_LABEL:
                    if (ch == ',')
                    {
                        label_buf[label_idx] = '\0';
                        k_state = READ_X;
                        x_idx = 0;
                    }
                    else if (label_idx < sizeof(label_buf) - 1)
                    {
                        label_buf[label_idx++] = ch;
                    }
                    break;

                case READ_X:
                    if (ch == ',')
                    {
                        x_buf[x_idx] = '\0';
                        k_state = READ_Y;
                        y_idx = 0;
                    }
                    else if (x_idx < sizeof(x_buf) - 1)
                    {
                        x_buf[x_idx++] = ch;
                    }
                    break;

                case READ_Y:     // 新增读取 Y 状态
                    if (ch == ',')
                    {
                        y_buf[y_idx] = '\0';
                        k_state = READ_DISTANCE;
                        d_idx = 0;
                    }
                    else if (y_idx < sizeof(y_buf) - 1)
                    {
                        y_buf[y_idx++] = ch;
                    }
                    break;

                case READ_DISTANCE:
                    if (d_idx < sizeof(dist_buf) - 1)
                    {
                        dist_buf[d_idx++] = ch;
                    }
                    break;
            }
        }
        rt_thread_mdelay(10);
    }
}

/* 阻塞发送单字节 */
void JXB_send_byte(rt_uint8_t group_id, rt_uint16_t run_times)
{
    // 构造数据帧
    rt_uint8_t cmd[7];

    cmd[0] = 0x55;
    cmd[1] = 0x55;
    cmd[2] = 0x05;                // 数据长度
    cmd[3] = 0x06;                // 指令编号 CMD_ACTION_GROUP_RUN
    cmd[4] = group_id;            // 参数1：动作组编号
    cmd[5] = run_times & 0xFF;    // 参数2：运行次数低8位
    cmd[6] = run_times >> 8;      // 参数3：运行次数高8位

    // 发送数据
    rt_device_write(JXB_serial, 0, cmd, sizeof(cmd));
}

// ====== 串口发送函数（使用RT-Thread）======
void Song_SendCode(uint8_t *data, uint8_t len)
{
    if (Song_serial != RT_NULL)
    {
        rt_device_write(Song_serial, 0, data, len);
    }
}

void JQ8x00_Command_Data(UartCommandData Command, uint8_t DATA)
{
    uint8_t Buffer[6] = {0xaa};
    uint8_t DataLen = 0;
    rt_kprintf("send ok\r\n");

    Buffer[1] = Command;

    if ((Command != AppointTrack) && (Command != SetCycleCount) &&
        (Command != SelectTrackNoPlay) && (Command != AppointTimeBack) &&
        (Command != AppointTimeFast))
    {
        Buffer[2] = 1;
        Buffer[3] = DATA;
        Buffer[4] = Buffer[0] + Buffer[1] + Buffer[2] + Buffer[3];
        DataLen = 5;
    }
    else
    {
        Buffer[2] = 2;
        Buffer[3] = DATA / 256;
        Buffer[4] = DATA % 256;
        Buffer[5] = Buffer[0] + Buffer[1] + Buffer[2] + Buffer[3] + Buffer[4];
        DataLen = 6;
    }
    #if JQ8x00_BusyCheck
    while(JQ8x00_BUSY_Read);                //忙检测
    #endif
    Song_SendCode(Buffer, DataLen);

}

